﻿// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// Website: https://www.blazor.zone or https://argozhang.github.io/

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;

namespace BootstrapBlazor.Components;

/// <summary>
/// <see cref="NavbarDropdownToggle"/> 组件
/// 控制下拉菜单的显示或隐藏切换
/// </summary>
public sealed partial class NavbarDropdownToggle : IDisposable
{
    /// <summary>
    /// 获得 样式集合
    /// </summary>
    /// <returns></returns>
    private string? ClassString => CssBuilder.Default()
        .AddClass("navbar-v-link navbar-v-dropdown-toggle", !ParentDropdownState.IsHorizontal)
        .AddClass("dropdown-item", ParentDropdownState.IsHorizontal && ParentDropdown?.IsDropdownSubmenu == true)
        .AddClass("nav-link dropdown-toggle", ParentDropdownState.IsHorizontal && ParentDropdown?.IsDropdownSubmenu != true)
        .AddClassFromAttributes(AdditionalAttributes)
        .Build();

    /// <summary>
    /// 获得 样式集合
    /// </summary>
    /// <returns></returns>
    private string? StyleClassString => CssBuilder.Default()
        .AddClass($"padding-{(ParentDropdownState.IsRTL ? "right" : "left")}: {Indentation * ParentDropdownState.Indent}rem!important;", ParentDropdownState.IsMixinDisplay || ParentDropdownState.IsPopoutDisplay)
        .AddStyleFromAttributes(AdditionalAttributes)
        .Build();

    private ElementReference ToggleElement { get; set; } = new();

    private JSInterop<NavbarDropdownToggle>? Interop { get; set; }

    /// <summary>
    /// 获得/设置 父级 <see cref="NavbarDropdown"/> 组件的状态
    /// </summary>
    [CascadingParameter]
    public NavbarDropdownState ParentDropdownState { get; set; } = new();

    /// <summary>
    /// 获得/设置 父级组件引用
    /// </summary>
    [CascadingParameter]
    public NavbarDropdown? ParentDropdown { get; set; }

    /// <summary>
    /// 获得/设置 缩进量（rem）
    /// </summary>
    [Parameter]
    public decimal Indentation { get; set; } = 1.5M;

    /// <summary>
    /// 获得/设置 切换按钮点击事件
    /// </summary>
    [Parameter]
    public EventCallback Clicked { get; set; }

    /// <summary>
    /// 获得/设置 子组件内容
    /// </summary>
    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    /// <summary>
    /// OnAfterRenderAsync
    /// </summary>
    /// <param name="firstRender"></param>
    /// <returns></returns>
    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);

        if (firstRender)
        {
            if (Interop == null)
            {
                Interop = new JSInterop<NavbarDropdownToggle>(JSRuntime);
            }
            await Interop.InvokeVoidAsync(this, ToggleElement, "bb_leave_navbar_dropdown_toggle");
        }
    }

    /// <summary>
    /// 切换按钮点击事件
    /// </summary>
    /// <returns></returns>
    private Task ClickHandler()
    {
        if (ParentDropdown != null)
        {
            return ParentDropdown.Toggle();
        }
        return Clicked.InvokeAsync();
    }

    /// <summary>
    /// 鼠标移入处理事件
    /// </summary>
    /// <returns></returns>
    public async Task OnMouseEnterHandler()
    {
        if (ParentDropdown is not null)
        {
            ParentDropdownState.HoverToggler = true;

            if (!ParentDropdownState.DropdownVisible)
            {
                await ParentDropdown.OnMouseEnterHandler();
            }
        }
    }

    /// <summary>
    /// 鼠标移出处理
    /// </summary>
    /// <returns></returns>
    [JSInvokable]
    public async Task MouseLeaveHandler()
    {
        if (ParentDropdown is not null)
        {
            ParentDropdownState.HoverToggler = false;

            if (ParentDropdown.HasHovered)
            {
                return;
            }

            await ParentDropdown.OnMouseLeaveHandler();
        }
    }

    /// <summary>
    /// Dispose
    /// </summary>
    /// <param name="disposing"></param>
    private void DisposeCore(bool disposing)
    {
        if (disposing)
        {
            Interop?.Dispose();
        }
    }

    /// <summary>
    /// Dispose 方法
    /// </summary>
    public void Dispose()
    {
        DisposeCore(true);
        GC.SuppressFinalize(this);
    }
}
